function isDeepEqual(a, b) {
    if (a === b)
        return true;
    if (a instanceof Date && b instanceof Date)
        return a.getTime() === b.getTime();
    if (!a || !b || (typeof a !== "object" && typeof b !== "object"))
        return a === b;
    return compareObjects(a, b);
}
function compareObjects(a, b) {
    let i, length, keys;
    if (a === null || a === undefined || b === null || b === undefined)
        return false;
    if (a.prototype !== b.prototype)
        return false;
    if (Array.isArray(a)) {
        if (!Array.isArray(b))
            return false;
        length = a.length;
        if (length != b.length)
            return false;
        for (i = length; i-- !== 0;)
            if (!isDeepEqual(a[i], b[i]))
                return false;
        return true;
    }
    if (a instanceof Map && b instanceof Map) {
        if (a.size !== b.size)
            return false;
        // Use Array.from to convert iterator to array for ES5 compatibility
        const aEntries = Array.from(a.entries());
        Array.from(b.entries());
        for (i of aEntries)
            if (!b.has(i[0]))
                return false;
        for (i of aEntries)
            if (!isDeepEqual(i[1], b.get(i[0])))
                return false;
        return true;
    }
    if (a instanceof Set && b instanceof Set) {
        if (a.size !== b.size)
            return false;
        // Use Array.from to convert iterator to array for ES5 compatibility
        const aEntries = Array.from(a.entries());
        for (i of aEntries)
            if (!b.has(i[0]))
                return false;
        return true;
    }
    if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
        // @ts-ignore
        length = a.length;
        // @ts-ignore
        if (length != b.length)
            return false;
        // @ts-ignore
        for (i = length; i-- !== 0;)
            if (a[i] !== b[i])
                return false;
        return true;
    }
    if (a.constructor === RegExp)
        return a.source === b.source && a.flags === b.flags;
    if (a.valueOf !== Object.prototype.valueOf)
        return a.valueOf() === b.valueOf();
    if (a.toString !== Object.prototype.toString)
        return a.toString() === b.toString();
    keys = Object.keys(a);
    length = keys.length;
    if (length !== Object.keys(b).length)
        return false;
    for (i = length; i-- !== 0;)
        if (!Object.prototype.hasOwnProperty.call(b, keys[i]))
            return false;
    for (i = length; i-- !== 0;) {
        const key = keys[i];
        if (!isDeepEqual(a[key], b[key]))
            return false;
    }
    return true;
}

export { isDeepEqual as default };
